package { // 1034, 1140
	import flash.sampler.NewObjectSample;
	import flash.display.Shader;
	import flash.filters.ShaderFilter;
	import flash.geom.Rectangle;
	import flash.geom.Point;
	import org.flixel.*;
 
	public class PlayState extends FlxState {
		public static const LEVEL_WIDTH:Number = 1760;
		public static const LEVEL_HEIGHT:Number = 8000;
		public var player:Player;
		public var timer:Number = 0;
		
		override public function create():void {
			FlxG.debug = false;
			//adds a 100px wide text field at position 0,0 (top left)
			//add(new FlxText(0, 0, 100, "Hello, World!"));
			FlxState.bgColor = 0xFFFFFFFF;
			this._dragEye = new DragEye(this._clickEye);
			FlxU.setWorldBounds(0, 0, 2000, 8000);
			
			this._tunnelShader = new Shader(new TunnelShaderCode());
			this._wavesShader = new Shader(new WavesShaderCode());
			this._filter = new ShaderFilter(this._tunnelShader);
			
			this.player = new Player(this._clickEye, this._dragEye);
			
			this._eyeBeam.loadGraphic(DragEyeBeamImg);// , 64);
			this._eyeBeam.alpha = 0.75;
			var difference:FlxPoint = new FlxPoint(
				this.player.x - 16 - this._dragEye.eye.x,
				this.player.y - this._dragEye.eye.y);
			var distance:Number = Utility.getLength(difference);
			this._eyeBeam.x = this._dragEye.eye.x - 128 +(difference.x * 0.5);
			this._eyeBeam.y = this._dragEye.eye.y + (difference.y * 0.5);
			//this._eyeBeam.origin = new FlxPoint(0, 0);
			//this._eyeBeam.x = this.player.x;
			//this._eyeBeam.y = this.player.y;
			this._timerText = new FlxText(
				0, FlxG.height - 85, FlxG.width, "");
			this._timerText.alpha = 0.75;
			this._timerText.scrollFactor = new FlxPoint(0, 0);
			this._timerText.setFormat("Nervous", 72, 0xFFFFFFFF, "right");
			
			var twirl:FlxSprite = new FlxSprite();
			twirl.loadGraphic(BgTwirlImg, true, false, 320, 240);
			twirl.addAnimation("Twirl", 
				[0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10 , 11, 12, 13], 30);
			twirl.play("Twirl");
			twirl.alpha = 0.4;
			twirl.scrollFactor = new FlxPoint(0, 0);
			
			//load maps
			this._map1.loadMap(new MapData1, TilesImg1, 8, 8);
			this._map2.loadMap(new MapData2, TilesImg2, 8, 8);
			this._map3.loadMap(new MapData3, TilesImg3, 8, 8);
			this._map4.loadMap(new MapData4, TilesImg4, 8, 8);
			
			FlxG.follow(this._eyeBeam, 5);// 2.5);
            //FlxG.followAdjust(1, 1);
            //FlxG.followBounds(1,1,640-1,480-1);
			
			this.make(3, BouncerEnemy);
			
			this.add(new BackgroundImage(0));
			this.add(new BackgroundImage(1));
			this.add(new BackgroundImage(2));
			this.add(new BackgroundImage(3));
			this.add(twirl);
			
			// Don't add backgrounds after this line
			this._backgroundIndex = this.defaultGroup.members.length;
			
			this.add(this._map1);
			this.add(this._map2);
			this.add(this._map3);
			this.add(this._map4);
			
			
			//this.add(new laserPulse());
			this.add(this._enemies);
			this.add(this.player);
			this.add(this._eyeBeam);
			this.add(this._clickEye);
			this._clickEyeIndex = this.defaultGroup.members.length - 1;
			this.add(this._dragEye);
			this.add(this._timerText);
		}
		
		override public function update():void {
			if (this.player.health <= 0)
				FlxG.state = new GameOverState(this.timer);
			else if (this.player.x > 1000 && this.player.y < 1100 && this._dragEye.isDragging) {
				if (!this._hasWon) {
					FlxG.playMusic(Game.WinMusic);
					this._couch = new Couch();
					FlxG.follow(this.player, 20);
					this.defaultGroup.members[8] = this._couch;
					this._hasWon = true;
					//FlxG.state = new MenuState();
					this._dragEye.exists = false;
					this._clickEye.exists = false;
					this._eyeBeam.exists = false;
					this._winStateTimer = 0;
					this._enemies.kill();
					this._clickEye.dilation = 0.9;
				}
			}

			if (this._hasWon) {
				if ((FlxG.mouse.justPressed() && this._winStateTimer > 5) ||
					(FlxG.keys.justPressed("SPACE")) ||
					(this._winStateTimer > 40))
				{
					FlxG.state = new MenuState();
				}
				if (this._winStateTimer > 8 && this._winStateTimer < 10) {
					this._timerText.visible = true;
					this._timerText.y = 0;
					this._timerText.size = 48;
					this._timerText.text = "Music By";
				}
				else if (this._winStateTimer >= 10 && this._winStateTimer < 15) {
					this._timerText.text = "ANDY NELSON \n and \n DAN POLAK";
				}
				else if (this._winStateTimer >= 15 && this._winStateTimer < 17) {
					this._timerText.text = "Everything Else By";
				}
				else if (this._winStateTimer >= 17 && this._winStateTimer < 22) {
					this._timerText.text = "JOHN MURPHY \n and DEVON SCOTTTUNKIN";
				}
				else if (this._winStateTimer >= 22) {
					this._timerText.visible = false;
				}
				else if (!this._couch.overlaps(this.player)) {
					var couchVelocity:FlxPoint = new FlxPoint(
						this.player.x - this._couch.x,
						this.player.y - this._couch.y);
					Utility.normalize(couchVelocity);
					var playerMag:Number = Utility.getLength(this.player.velocity);
					this._couch.velocity.x = couchVelocity.x * 1.5 * playerMag;
					this._couch.velocity.y = couchVelocity.y * 1.5 * playerMag;
				}
				else {
					this.player.moves = false;
					this._couch.velocity = this.player.velocity;
					
				}
				this._winStateTimer += FlxG.elapsed;
			}
			else {
				FlxU.collide(this.player, this._map1);
				FlxU.collide(this.player, this._map2);
				FlxU.collide(this.player, this._map3);
				FlxU.collide(this.player, this._map4);
				FlxU.collide(this._enemies, this._map1);
				FlxU.collide(this._enemies, this._map2);
				FlxU.collide(this._enemies, this._map3);
				FlxU.collide(this._enemies, this._map4);
				this.timer += FlxG.elapsed;
				this._timerText.text = this.timer.toFixed();
			}
			var bounds:FlxObject = new FlxObject(player.x - 1000, player.y - 1000, player.x + 1000, player.y + 1000);
			//FlxU.setWorldBounds(bounds.x, bounds.y, bounds.width, bounds.height);
			var difference:FlxPoint = new FlxPoint(
				this.player.x - 16 - this._dragEye.eye.x,
				this.player.y - this._dragEye.eye.y);
			var distance:Number = Utility.getLength(difference);
			if (this._eyeBeam.exists) {
				this._eyeBeam.x = this._dragEye.eye.x - 128 +(difference.x * 0.5);
				this._eyeBeam.y = this._dragEye.eye.y + (difference.y * 0.5);
				this._eyeBeam.angle = FlxU.getAngle(difference.x, difference.y);
				this.player.angle = this._eyeBeam.angle - 90;
				Utility.normalize(difference);
				this._eyeBeam.scale.x = (distance / (this._eyeBeam.frameWidth - 50));
			}
			if (FlxG.keys.justPressed("ESCAPE")) {
				FlxG.state = new MenuState();
			}
			const MAX_ATTEMPTS:uint = 10;
			var isColliding:Boolean = false; 
			var attemptCount:uint = 0; 
			var oldX:Number;
			var oldY:Number;
			var enemyScreen:FlxPoint;
			for each(var enemy:FlxObject in this._enemies.members) {
					//for each (var existingEnemy:FlxObject in this._enemies) { 
						//isColliding = existingEnemy.overlaps(enemy); 
						//if (isColliding) 
							//break;
						//isColliding = FlxU.collide(enemy, this._map1);
						//if (isColliding) 
							//break;
						//isColliding = FlxU.collide(enemy, this._map2);
						//if (isColliding) 
							//break;
						//isColliding = FlxU.collide(enemy, this._map3);
						//if (isColliding) 
							//break;
						//isColliding = FlxU.collide(enemy, this._map4);
						//if (isColliding) 
							//break;
					//} ++attemptCount; 
				//} while (!isColliding && attemptCount < MAX_ATTEMPTS); 
				//if (isColliding) {
					//enemy.x = oldX;
					//enemy.y = oldY;
				//}
					
					
					
				if (FlxU.collide(enemy, this.player)) {
					if (!this.player.flickering()) {
						FlxG.play(Game.MonsterSound);
						this.player.health -= 1;
						this.player.flicker(1);
						enemy.flicker(1);
					}
				}
				enemyScreen = enemy.getScreenXY();
				var bleed:FlxPoint = new FlxPoint(
					200, 200);
				if ((enemyScreen.x >= -bleed.x && 
						enemyScreen.x < (FlxG.width + bleed.x)) &&
					(enemyScreen.y >= -bleed.y && 
						enemyScreen.y < (FlxG.height + bleed.y)))
				{
					continue;
				}
				//do { 
					oldX = enemy.x;
					oldY = enemy.y;
					enemy.x = bounds.x + (FlxU.random() * bounds.width);
					enemy.y = bounds.y + (FlxU.random() * bounds.height);
					enemy.velocity = new FlxPoint(100, 0);
			}

			if (this._dragEye.eye.overlaps(this._clickEye.eye)) {
				this._dragEye.update();
			}
			super.update();
		}
		
		override public function render():void {
			var o:FlxObject;
			var l:uint = this.defaultGroup.members.length;
			var eyeScreen:FlxPoint = this._dragEye.eye.getScreenXY();
			for (var i:uint = 0; i < l; i++) {
				
				// Apply filter after background is drawn.
				if ((i == this._backgroundIndex && this._dragEye.isDragging && 
						this._clickEye.dilation > 0) ||
					(i == this._clickEyeIndex && this._clickEye.dilation <= 0)) 
				{ 				
					if (i == this._clickEyeIndex) {
						o = this.defaultGroup.members[i+1] as FlxObject;
						if((o != null) && o.exists && o.visible)
							o.render();
					}
						
					this._filter.shader = this._tunnelShader;
					this._filter.shader.data.imgSize.value = 
						[FlxG.width, FlxG.height];
					this._filter.shader.data.center.value = 
						[eyeScreen.x+25, eyeScreen.y+25];
					FlxG.buffer.applyFilter(
						FlxG.buffer,
						new Rectangle(0, 0, FlxG.width, FlxG.height),
						new Point(0, 0),
						this._filter);
						
					if ( i == this._clickEyeIndex) {
						o = this.defaultGroup.members[i] as FlxObject;
						if((o != null) && o.exists && o.visible)
							o.render();
						i++;
						continue;
					}
				}
				
				//if (i == 9 && this._clickEye.dilation <= 0) {
					//this._filter.shader = this._wavesShader;
					//this._filter.shader.data.imgSize.value = [FlxG.width, FlxG.height];
					//this._filter.shader.data.center.value = 
						//[eyeScreen.x, eyeScreen.y];
					//this._filter.shader.data.offset.value = 
						//[this.timer * 0.0001, this.timer * 0.0002];
					//FlxG.buffer.applyFilter(
						//FlxG.buffer,
						//new Rectangle(0, 0, FlxG.width, FlxG.height),
						//new Point(0, 0),
						//this._filter);
				//}
				
				o = this.defaultGroup.members[i] as FlxObject;
				if((o != null) && o.exists && o.visible)
					o.render();
			}
		}
		
		override public function postProcess():void {
			//if (this._clickEye.dilation <= 0) {
				//this._filter.shader = this._wavesShader;
				//var eyePosition:FlxPoint = this._dragEye.getScreenXY();
				//this._filter.shader.data.imgSize.value = [FlxG.width, FlxG.height];
				//var bob:Number = FlxG.width;
				//this._filter.shader.data.center.value = 
					//[eyePosition.x + 400, eyePosition.y + 2050];
				//this._filter.shader.data.offset.value = 
					//[this.timer * 0.0001, this.timer * 0.0002];
				//FlxG.buffer.applyFilter(
					//FlxG.buffer,
					//new Rectangle(0, 0, FlxG.width, FlxG.height),
					//new Point(0, 0),
					//this._filter);
			//}
		}
		
		protected function make(enemyCount:uint, EnemyType:Class):void { 
					for (var i:uint = 0; i < enemyCount; i++)
						this._enemies.add(new EnemyType());
		}

		// embedded images
		[Embed(source = '../content/DragEyeBeam.png')] 
			private var DragEyeBeamImg:Class;
		[Embed(source = '../content/BgTwirl.png')] 
			private var BgTwirlImg:Class;
			
		// tile map images
		[Embed(source = '../content/bubbleHippieTiles.png')] 
			private var TilesImg1:Class;
		[Embed(source='../content/midLevelFreakoutTiles.png')]
			private var TilesImg2:Class;
		[Embed(source='../content/SpaceMadnessTiles.png')] 
			private var TilesImg3:Class;
		[Embed(source='../content/MountainTopTiles.png')]
			private var TilesImg4:Class;
		// map data
		[Embed(source = '../content/MapLayer1.txt', mimeType = "application/octet-stream")] 
			private var MapData1:Class;
		[Embed(source = '../content/MapLayer2.txt', mimeType = "application/octet-stream")] 
			private var MapData2:Class;
		[Embed(source = '../content/MapLayer3.txt', mimeType = "application/octet-stream")] 
			private var MapData3:Class;
		[Embed(source = '../content/MapLayer4.txt', mimeType = "application/octet-stream")] 
			private var MapData4:Class;
			
		[Embed(source = '../content/Waves.pbj', mimeType = "application/octet-stream")] 
			private var WavesShaderCode:Class;
		[Embed(source = '../content/Tunnel.pbj', mimeType = "application/octet-stream")] 
			private var TunnelShaderCode:Class;
		[Embed(source = "../content/Nervous.ttf", fontFamily = "Nervous", embedAsCFF="false")] 	
			private var MonFont:String;

		private var _wavesShader:Shader;
		private var _tunnelShader:Shader;
		private var _filter:ShaderFilter;
		private var _eyeBeam:FlxSprite = new FlxSprite();
		private var _clickEye:ClickEye = new ClickEye();
		private var _dragEye:DragEye;
		private	var _timerText:FlxText;
		private	var _map1:FlxTilemap = new FlxTilemap();
		private var _map2:FlxTilemap = new FlxTilemap();
		private var _map3:FlxTilemap = new FlxTilemap();
		private var _map4:FlxTilemap = new FlxTilemap();
		private var _enemies:FlxGroup = new FlxGroup();
		private var _clickEyeIndex:uint;
		private var _backgroundIndex:uint;
		private var _hasWon:Boolean = false;
		private var _couch:Couch;
		private var _winStateTimer:Number;
	}
}


